package sevencm.wechat.export.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import sevencm.wechat.common.BeanRegister;
import sevencm.wechat.common.DynamicDataSource;
import sevencm.wechat.common.ExportExcel;
import sevencm.wechat.entity.Friend;
import sevencm.wechat.entity.ManifestFiles;
import sevencm.wechat.entity.WechatMM;
import sevencm.wechat.mapper.ManifestDao;
import sevencm.wechat.vo.*;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class ExportServiceImpl implements ExportService {

    @Value("${manifest.db.path}")
    private String manifestDBPath;

    @Autowired
    private ManifestDao manifestDao;

    @Autowired
    private BeanRegister beanHolder;

    @PostConstruct
    @Override
    public Map<String, WechatDB> getWechatDBInfo() {
        List<ManifestFiles> files = manifestDao.getAppData("AppDomain-com.tencent.xin").stream().filter(
                manifestFiles ->
                        manifestFiles.getRelativePath().endsWith("MM.sqlite")
                                || manifestFiles.getRelativePath().endsWith("WCDB_Contact.sqlite")
                                || manifestFiles.getRelativePath().matches(".*message_[0-9]\\.sqlite")
        ).collect(Collectors.toList());

        //记录账号数据库信息数据
        Map<String, WechatDB> wechatDBMap = new HashMap<>();

        //生成相关账号数据库信息数据
        files.stream().forEach(manifestFiles -> {
            String[] dbInfo = manifestFiles.getRelativePath().split("/");
            String fileID = manifestFiles.getFileID();
            String account = dbInfo[1];
            String dbName = dbInfo[3];
            WechatDB wechatDB = wechatDBMap.get(account);
            if (wechatDB == null) {
                wechatDB = new WechatDB();
                wechatDB.setAccountMD5(account);
                List<WechatDBItem> dbItems = new ArrayList<>();
                wechatDB.setDbItems(dbItems);
                wechatDBMap.put(account, wechatDB);
            }
            WechatDBItem dbItem = new WechatDBItem();
            dbItem.setFileID(fileID);
            dbItem.setSqliteName(dbName);
            dbItem.setDbPath(manifestDBPath + fileID.substring(0, 2) + "/" + fileID);
            wechatDB.getDbItems().add(dbItem);
        });

        //处理消息数据
        wechatDBMap.forEach((s, wechatDB) -> {
            //联系人
            List<WechatContact> wechatContactList = new ArrayList<>();
            //聊天信息：MD5 + 聊天记录list
            Map<String,List<WechatMM>> wechatMMDataMap = new HashMap<>();

            for(WechatDBItem item: wechatDB.getDbItems()){
                //记录本微信号的联系人
                DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
                dataSourceBuilder.driverClassName("org.sqlite.JDBC");
                dataSourceBuilder.url("jdbc:sqlite:"+item.getDbPath());
                DataSource dataSource = dataSourceBuilder.build();
                DynamicDataSource.dataSourcesMap.put("tempds", dataSource);
                DynamicDataSource.setDataSource("tempds");

                if(item.getSqliteName().equals("WCDB_Contact.sqlite")){
                    //微信联系人
                    List<Friend> list = manifestDao.getDBConnect();
                    for(Friend friend:list){
                        WechatContact contact = new WechatContact();
                        contact.setWxID(friend.getUserName());
                        buildName(friend.getDbContactRemark(),contact);
                        buildProfile(friend.getDbContactProfile(),contact);
                        wechatContactList.add(contact);
                    }
                }else{
                    List<String> tables = manifestDao.getMessageDBTables();
                    for(String table:tables){
                        if(table.startsWith("Chat_")){
                            String md5 = table.replace("Chat_","");
                            List<WechatMM> wechatMMList = manifestDao.getIMData(table);
                            List<WechatMM> exitList = wechatMMDataMap.get(md5);
                            if(exitList==null){
                                exitList = new ArrayList<>();
                                wechatMMDataMap.put(md5,exitList);
                            }
                            if(wechatMMList!=null && wechatMMList.size()>0){
                                exitList.addAll(wechatMMList);
                            }
                        }
                    }
                }
            }

            Map<String,WechatContact> wxIDMap = new HashMap<>();
            for(WechatContact contact:wechatContactList){
                wxIDMap.put(contact.getWxID(),contact);
            }


            for(WechatContact contact:wechatContactList){
                List<WechatMMDataExport> dataExports = new ArrayList<>();
                List<WechatMM> mmList = wechatMMDataMap.get(DigestUtils.md5DigestAsHex(contact.getWxID().getBytes()));
                if(mmList!=null && mmList.size()>0){
                    //System.out.println("来自：" + contact.getNick() + "的聊天记录");

                    for(WechatMM mm:mmList){
                        WechatMMDataExport export = new WechatMMDataExport();
                        export.setRoom(contact.getNick());
                        export.setCreateTime(timestamp2Date(mm.getCreateTime()));
                        if(contact.getWxID().contains("@chatroom")){
                            String[] messageData = mm.getMessage().split(":\n",2);
                            if(messageData.length<2){
                                export.setMessage(mm.getMessage());
                            }else{
                                WechatContact roomConcat =  wxIDMap.get(messageData[0]);
                                export.setTalkUser(roomConcat==null?"未知":roomConcat.getNick());
                                export.setMessage(messageData[1]);
                            }
                        }else{
                            if(mm.getDes()==0){
                                export.setTalkUser("我");
                            }else{
                                export.setTalkUser(contact.getNick());
                            }
                            export.setMessage(mm.getMessage());
                        }
                        dataExports.add(export);
//                        if(export.getRoom()!=null && export.getMessage().contains("密码")){
//                            System.out.println(export);
//                            break;
//                        }


                        // debug ----------------------
//                        StringBuilder builder = new StringBuilder();
//                        builder.append("\t\t");
//                        builder.append(timestamp2Date(mm.getCreateTime()));
//                        builder.append("\t");
//                        //群聊
//                        if(contact.getWxID().contains("@chatroom")){
//                            String[] messageData = mm.getMessage().split(":\n",2);
//                            if(messageData.length<2){
//                                builder.append(mm.getMessage());
//                            }else{
//                                WechatContact roomConcat =  wxIDMap.get(messageData[0]);
//                                builder.append(roomConcat==null?"未知":roomConcat.getNick());
//                                builder.append("@chatroom：");
//                                builder.append(messageData[1]);
//                            }
//                        }else{
//                            if(mm.getDes()==0){
//                                builder.append("我：");
//                            }else{
//                                builder.append(contact.getNick()+ "：");
//                            }
//                            builder.append(mm.getMessage());
//                        }
//                        //builder.append(wxIDMap.get())
//                        System.out.println(builder);
                        // debug ----------------------





                    }
                }

                if(dataExports.size()>0){
                    List<String> listName = new ArrayList<>();
                    listName.add("聊天对象");
                    listName.add("发言者");
                    listName.add("聊天内容");
                    listName.add("日期");
                    List<String> listId = new ArrayList<>();
                    listId.add("room");
                    listId.add("talkUser");
                    listId.add("message");
                    listId.add("createTime");

                    ExportExcel<WechatMMDataExport> exportExcel = new ExportExcel<>();
                    String sheetName = contact.getNick()==null?System.currentTimeMillis() + "未知" :contact.getNick();
                    sheetName = sheetName.replaceAll("/","-").replace("*","").replaceAll("\\s*", "")
                            .replaceAll("\\|","");
                    exportExcel.exportExcel("聊天导出-" + s + "-" + sheetName + ".xls"
                            ,sheetName, listName, listId,
                            dataExports);
                }



            }



        });
        return wechatDBMap;
    }


    /**
     * 获取分割inx
     * @param bytes
     * @return
     */
    private void buildName(byte[] bytes,WechatContact contact){
        for(int i=0;i<bytes.length;){
            int length = bytes[i+1];
            if(length<=0 || (i + 2 + length)>bytes.length){
                break;
            }
            switch(bytes[i]){
                case 0x0a://昵称
                case 0x12://微信号
                case 0x1a://备注名
                case 0x22://备注名自动拼音
                case 0x2a://备注名自动首字母
                case 0x32://昵称自动拼音 或 chatroom
                    byte[] country = subBytes(bytes,i+2,length);
                    contact.setNick(new String(country));
                    i = i + 2 + length;
                    return;
            }

            i++;
        }
    }

    private void buildProfile(byte[] bytes,WechatContact contact){
        for(int i=0;i<bytes.length;){
            int length = bytes[i+1];
            if(length<=0){
                break;
            }
            switch(bytes[i]){
                case 0x08: //男 女
                    switch (bytes[i+1]){
                        case 1:
                            contact.setGender("男");
                            break;
                        case 2:
                            contact.setGender("女");
                            break;
                    }
                    i = i + 2;
                    continue;
                case 0x12:// country
                case 0x1a:// state
                case 0x22:// city
                case 0x2a://signature
                    byte[] dataByte = subBytes(bytes,i+2,length);
                    String data = new String(dataByte);


                    if(bytes[i]==0x12){
                        contact.setCountry(data);
                    }else if(bytes[i]==0x1a){
                        contact.setState(data);
                    }else if(bytes[i]==0x22){
                        contact.setCity(data);
                    }else if(bytes[i]==0x2a){
                        contact.setSignature(data);
                    }
                    i = i + 2 + length;
                    continue;
            }
            i++;
        }
    }

    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        for (int i=begin; i<begin+count; i++) bs[i-begin] = src[i];
        return bs;
    }


    public static String timestamp2Date(long timeStamp){
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sd2 = sdf2.format(new Date(timeStamp*1000));
       return sd2;
    }

}
